package com.insight.modules.system.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuanqiao.insight.acore.system.entity.ConfigureDict;
import com.yuanqiao.insight.acore.system.entity.ConfigureDictItem;
import com.yuanqiao.insight.acore.system.mapper.ConfigureDictMapper;
import com.yuanqiao.insight.common.util.common.LocalCacheUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import com.insight.common.api.vo.Result;
import com.insight.common.aspect.annotation.AutoLog;
import com.insight.common.constant.CommonConstant;
import com.insight.common.mq.RedisMq;
import com.insight.common.mq.stream.Streams;
import com.insight.common.system.query.QueryGenerator;
import com.yuanqiao.insight.acore.system.service.IConfigureDictItemService;
import com.yuanqiao.insight.acore.system.service.IConfigureDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Optional;

/**
 * <p>
 * 配置字典表 前端控制器
 * </p>
 *
 * @Author zhangweijian
 * @since 2018-12-28
 */
@RestController
@RequestMapping("/configure/dict")
@Slf4j
public class ConfigureDictController {

    // 注入配置字典服务接口，实现字典的业务操作
    @Autowired
    private IConfigureDictService configureDictService;

    // 注入配置字典的MyBatis Mapper，直接执行数据库操作
    @Autowired
    private ConfigureDictMapper configureDictMapper;

    // 注入配置字典项服务，操作字典项相关数据
    @Autowired
    private IConfigureDictItemService configureDictItemService;

    // 注入Redis消息队列，用于发布刷新事件
    @Autowired
    private RedisMq redisMq;

    // 本地缓存工具实例，单例模式
    private final LocalCacheUtils localCacheUtils = LocalCacheUtils.getInstance();

    /**
     * 配置字典分页查询接口
     *
     * 支持根据字典名称(dictName)和字典编码(dictCode)模糊查询。
     * 当系统开启“三权分立”(isThreePowers==1)时，会排除字典编码为"insight_threePowers"的数据。
     * 查询结果按照创建时间倒序排序。
     *
     * @param configureDict  查询条件封装实体，主要用于封装查询参数
     * @param pageNo        当前页码，默认值为1
     * @param pageSize      每页查询数量，默认10
     * @param req           HttpServletRequest对象，用于获取请求参数
     * @return Result封装的分页结果，包含符合条件的配置字典数据页
     */
    @AutoLog(value = "配置字典-列表展示")
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public Result<IPage<ConfigureDict>> queryPageList(ConfigureDict configureDict,
                                                      @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                      @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                      HttpServletRequest req) {
        // 提取字典名称和字典编码，方便做模糊查询
        String dictName = configureDict.getDictName();
        String dictCode = configureDict.getDictCode();

        // 清空实体中的dictName和dictCode，避免QueryGenerator重复匹配
        if (StringUtils.isNotBlank(dictName)) {
            configureDict.setDictName(null);
        }
        if (StringUtils.isNotBlank(dictCode)) {
            configureDict.setDictCode(null);
        }

        // 根据请求参数构造查询条件Wrapper
        QueryWrapper<ConfigureDict> queryWrapper = QueryGenerator.initQueryWrapper(configureDict, req.getParameterMap());

        // 如果字典名称非空，则加入模糊查询条件
        if (StringUtils.isNotBlank(dictName)) {
            queryWrapper.like("dict_name", dictName);
        }
        // 如果字典编码非空，则加入模糊查询条件
        if (StringUtils.isNotBlank(dictCode)) {
            queryWrapper.like("dict_code", dictCode);
        }

        // 判断本地缓存中三权分立是否启用，启用时排除dict_code为"insight_threePowers"的字典
        String threePowersKey = com.yuanqiao.insight.common.constant.CommonConstant.DATA_DICT_KEY + "insight_threePowers";
        Optional<Object> optional = Optional.ofNullable(localCacheUtils.getValueByKey(threePowersKey + "_isEnable"));
        int isThreePowers = Integer.parseInt(String.valueOf(optional.orElse("0")));
        if (isThreePowers == 1) {
            queryWrapper.ne("dict_code", "insight_threePowers");
        }

        // 按创建时间降序排序，最新创建的数据优先显示
        queryWrapper.orderByDesc("create_time");

        // 创建分页对象，封装分页参数
        Page<ConfigureDict> page = new Page<>(pageNo, pageSize);

        // 执行分页查询
        IPage<ConfigureDict> pageList = configureDictService.page(page, queryWrapper);

        // 返回查询结果，封装成统一的Result对象
        return Result.OK(pageList);
    }

    /**
     * 新增配置字典
     *
     * 设置创建时间为当前时间，逻辑删除标记为未删除，调用服务保存新字典。
     *
     * @param configureDict 配置字典实体对象，包含字典名称、编码等信息
     * @return 添加操作结果封装
     */
    @AutoLog(value = "配置字典-添加")
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public Result<?> add(@RequestBody ConfigureDict configureDict) {
        // 设置当前创建时间
        configureDict.setCreateTime(new Date());
        // 设置逻辑删除标记为未删除状态
        configureDict.setDelFlag(CommonConstant.DEL_FLAG_0);
        // 调用服务保存字典对象
        configureDictService.save(configureDict);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑配置字典
     *
     * 根据字典实体中的ID更新对应记录。
     * 更新后发布字典刷新事件，通知其他系统刷新缓存。
     *
     * @param configureDict 修改后的字典实体
     * @return 编辑操作结果封装
     */
    @AutoLog(value = "配置字典-编辑")
    @RequestMapping(value = "/edit", method = RequestMethod.PUT)
    public Result<?> edit(@RequestBody ConfigureDict configureDict) {
        // 更新数据库中的字典记录
        configureDictService.updateById(configureDict);
        // 发送刷新事件通知缓存更新
        sendEvent();
        return Result.OK("编辑成功！");
    }

    /**
     * 删除配置字典
     *
     * 根据字典ID删除对应的配置字典，同时删除该字典对应的所有字典项。
     * 删除后发送刷新事件，通知缓存刷新。
     *
     * @param id 配置字典ID
     * @return 删除操作结果封装
     */
    @AutoLog(value = "配置字典-删除")
    @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        // 删除字典表中的记录
        configureDictMapper.deleteById(id);
        // 删除对应的所有字典项
        configureDictItemService.remove(new QueryWrapper<ConfigureDictItem>().eq("dict_id", id));
        // 发送刷新事件，通知其他系统刷新缓存
        sendEvent();
        return Result.OK("删除成功！");
    }

    /**
     * 发送配置字典刷新事件
     *
     * 通过Redis消息队列发布一个空的JSON对象，通知消费者刷新缓存。
     */
    private void sendEvent() {
        redisMq.publish(Streams.CONFIGURE_DICT_REFRESH, new JSONObject());
    }

    /**
     * 手动刷新全部配置字典缓存接口
     *
     * 调用发送刷新事件接口，触发所有消费者刷新字典缓存。
     *
     * @return 刷新操作结果封装
     */
    @RequestMapping(value = "/refresh", method = RequestMethod.GET)
    public Result<?> reFresh() {
        sendEvent();
        return Result.OK("刷新成功！");
    }

}

